import InitialConfig from "./interface/initialConfig";
import Pkg from "./utils/pkg";
const fs = require("fs");
const fse = require("fs-extra");
const path = require("path");
const ora = require("ora");
const prettier = require("prettier");

const inquirer = require("inquirer");
const chalk = require("chalk");
const log = console.log;
const cwd = process.cwd();

let projectPath: string;
let dirName: string;

const { program } = require("commander");
const execa = require("execa");
program.version("0.0.1").description("一个脚手架工具");

program
  .command("init <name>")
  .description("init project")
  .action((name) => {
    try {
      if (fs.existsSync(path.join(cwd, name))) {
        throw new Error("文件夹已存在");
      }

      dirName = name;
      projectPath = path.join(cwd, name);
    } catch (error) {
      log(chalk.red(error.message));
      process.exit(0);
    }

    let config: InitialConfig = {
      name: "",
      framework: "",
      useBabel: true,
      useWebpack: true,
      libraries: [],
      css: [],
      manager: "",
      ready: false,
    };

    inquirer
      .prompt([
        {
          type: "input",
          name: "name",
          message: "project name",
          validate: function (input) {
            const done = this.async();
            const name = input.trim();
            if (!name.length) {
              done("name is required");
              return;
            }
            if (/^-/.test(name) || /-$/.test(name) || !/^[a-z\-]+$/.test(name)) {
              done("name is invalid");
              return;
            }
            done(null, true);
          },
        },
        {
          type: "list",
          name: "framework",
          choices: ["react"],
          message: "which framework",
          default: 0,
        },
        {
          type: "checkbox",
          name: "libraries",
          choices: ["react-router-dom", "react-redux"],
          when: function (answers) {
            if (answers.framework === "react") {
              return true;
            }
            return false;
          },
        },
        {
          type: "checkbox",
          name: "css",
          message: "which css pre-processor?",
          choices: ["sass", "less"],
          default: 1,
        },
        {
          type: "list",
          name: "manager",
          message: "which package manager?",
          choices: ["npm", "yarn", "cnpm", "pnpm"],
          default: 0,
        },
        {
          type: "confirm",
          name: "ready",
          message: "Are you ready?",
        },
      ])
      .then(async function (initConfig) {
        const answers: InitialConfig = Object.assign({}, config, initConfig);

        if (!answers.ready) return;

        fs.mkdirSync(name);

        const spinner = ora("init package.json");
        spinner.start();

        const install_spinner = ora("install packages");

        try {
          Pkg.instance.name = answers.name;

          if (answers.framework === "react") {
            Pkg.instance.injectPrompt("react");
          }

          answers.libraries.forEach((c: string) => {
            Pkg.instance.injectPrompt(c);
          });

          answers.css.forEach((c: string) => {
            Pkg.instance.injectPrompt(c);
          });

          if (answers.useBabel) {
            Pkg.instance.injectPrompt("babel");
          }

          if (answers.useWebpack) {
            Pkg.instance.injectPrompt("webpack");
          }

          // 复制模版
          fse.copySync(path.join(__dirname, `../templates/${answers.framework}-template`), projectPath, { overwrite: true });

          const templatePkg = require(path.join(__dirname, `../templates/${answers.framework}-template/package.json`));
          fs.writeFileSync(path.join(projectPath, "./package.json"), prettier.format(JSON.stringify({ ...Pkg.instance.toJSON(), ...templatePkg }), { parser: "json" }));
          spinner.succeed();

          // 安装依赖
          await new Promise<void>((resolve, reject) => {
            const c = execa(`${answers.manager}`, require(path.join(__dirname, `./manager/${answers.manager}.js`)).install, { cwd: projectPath });
            c.stdout.on("data", (buffer) => {
              log(chalk.blue(buffer));
            });
            c.on("close", () => {
              resolve();
            });
            c.on("exit", () => {
              resolve();
            });
            c.catch((err: Error) => {
              reject(err);
            });
          })
            .then(() => {
              install_spinner.succeed();
              log(chalk.green("依赖安装完成!"));
            })
            .catch((err) => {
              log(chalk.red(err.message));
              install_spinner.fail();
            });
          log(chalk.green("\n按照一下步骤开始开发吧\n"));
          log(chalk.green(` cd ${dirName} \n`));
          log(chalk.green(" npm run dev\n"));
          process.exit(0);
        } catch (error) {
          log(chalk.red(error.message));
          install_spinner.fail();
        }
      });
  });

program.parse(process.argv);
